package me.sdevil507.org.service.impl;

import com.querydsl.core.types.Predicate;
import lombok.extern.slf4j.Slf4j;
import me.sdevil507.biz.common.exceptions.PhoneNumberExistedException;
import me.sdevil507.org.dto.OrgExpertInfoParamsDto;
import me.sdevil507.org.dto.OrgUserParamsDto;
import me.sdevil507.org.mapper.OrgExpertInfoMapper;
import me.sdevil507.org.mapper.OrgUserMapper;
import me.sdevil507.org.po.*;
import me.sdevil507.org.repository.*;
import me.sdevil507.org.service.OrgExpertService;
import me.sdevil507.org.service.OrgInviteService;
import me.sdevil507.org.service.TempExpertService;
import me.sdevil507.supports.helper.Md5PasswordHelper;
import me.sdevil507.supports.result.ApiResultDTO;
import me.sdevil507.supports.result.ApiResultGenerator;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import me.sdevil507.supports.status.ApiStatusCode;
import me.sdevil507.supports.util.AESUtil;
import me.sdevil507.supports.util.PhoneFormatCheckUtils;
import me.sdevil507.supports.util.RegularExpressionUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
@Slf4j
public class OrgExpertServiceImpl implements OrgExpertService {

    @Autowired
    OrgUserRepository orgUserRepository;

    @Autowired
    private OrgUserMapper orgUserMapper;
    @Autowired
    private OrgExpertInfoMapper orgExpertInfoMapper;
    @Autowired
    private OrgRepository orgRepository;
    @Autowired
    private OrgUserRelRepository orgUserRelRepository;
    @Autowired
    private OrgExpertInfoRepository orgExpertInfoRepository;
    @Resource
    private OrgDeptRepository orgDeptRepository;
    @Autowired
    private OrgInviteService orgInviteService;
    @Autowired
    private OrgInviteRepository orgInviteRepository;
    @Autowired
    private TempExpertService tempExpertService;
    @Autowired
    private Md5PasswordHelper md5PasswordHelper;


    @Override
    public void create(OrgUserParamsDto dto, Long orgId) throws PhoneNumberExistedException {
//        OrgUserRelPo orgUserRelPo = phoneNumberExisted(dto.getPhoneNumber(), orgId);
        OrgUserRelPo orgUserRelPo = nameExisted(dto.getRealName(), orgId);
        //查询专家信息
        OrgUserPo orgUserPo = this.findOrgUserByPhoneAndRealName(dto.getPhoneNumber(), dto.getRealName());
        String password = AESUtil.encryptPassword(AESUtil.DEFAULT_PASSWORD);
        //判断专家是否已在本机构存在---查询对应关系
        if(orgUserRelPo != null){
            //如果已经是专家
            if (orgUserRelPo.isExpert()) {
                throw new PhoneNumberExistedException("当前专家在该机构下已存在!");
            }
            //如果专家信息为空
            if(orgUserPo.getExpertInfo() == null){
                OrgExpertInfoPo orgExpertInfoPo = orgExpertInfoRepository.save(orgExpertInfoMapper.dto2po(dto.getExpertInfo()));
                orgUserPo.setExpertInfo(orgExpertInfoPo);
                orgUserPo.setPassword(password);
                orgUserRepository.save(orgUserPo);
            }
        }else{

//            //判断当前机构下 邀请记录是否存在
//            OrgInvitePo orgInvitePo = orgInviteService.existedInviteRecord(dto.getPhoneNumber(), dto.getRealName());
//            if(orgInvitePo != null){
//                //删除邀请记录
//                orgInviteRepository.delete(orgInvitePo);
//            }
//            //TODO 判断当前机构下 待邀请中是否存在
//            ExpertSearchDto expertSearchDto = new ExpertSearchDto();
//            expertSearchDto.setAuthor(dto.getRealName());
//            List<TempExpertPo> tempExpertPoList = tempExpertService.readAllByOrg(expertSearchDto);


            orgUserRelPo = new OrgUserRelPo();
            //查询当前机构
//            OrgPo orgPo = orgRepository.findById(orgId).orElse(null);
            OrgDeptPo orgDeptPo = orgDeptRepository.findById(orgId).orElse(null);
            orgUserRelPo.setOrg(orgDeptPo);
            //查询是否在云专家库下存在
            if(orgUserPo != null){
                orgUserRelPo.setUser(orgUserPo);
                orgUserRelPo.setFullTime(dto.getExpertInfo().getFullTime());
                orgUserRelPo.setLeader(dto.getExpertInfo().getLeader());
            }else{
                //如果不存在---则添加云库信息---并添加对应关系--orgUser--orgExpertInfo
                orgUserPo = orgUserMapper.dto2po(dto);
                orgUserRelPo.setFullTime(dto.getExpertInfo().getFullTime());
                orgUserRelPo.setLeader(dto.getExpertInfo().getLeader());
                //先保存专家信息
                if (null != orgUserPo.getExpertInfo()) {
                    OrgExpertInfoPo orgExpertInfoPo = orgExpertInfoRepository.save(orgUserPo.getExpertInfo());
                    orgUserPo.setExpertInfo(orgExpertInfoPo);
                }
                orgUserPo.setPassword(password);
                orgUserRepository.save(orgUserPo);

                orgUserRelPo.setUser(orgUserPo);
            }
        }
        orgUserRelPo.setExpert(true);
        // 保存
        orgUserRelRepository.save(orgUserRelPo);
    }

    /**
     * 判断手机号码是否在云专家库下存在
     *
     * @param phoneNumber 手机号码
     * @return 执行反馈
     */
    public OrgUserPo findOrgUserByPhoneAndRealName(String phoneNumber, String realName) {
        QOrgUserPo qOrgUserPo = QOrgUserPo.orgUserPo;
        Predicate predicate = qOrgUserPo.id.isNotNull()
                .and(qOrgUserPo.deleted.isFalse())
                .and(qOrgUserPo.phoneNumber.eq(phoneNumber))
                .and(qOrgUserPo.realName.eq(realName));
        return orgUserRepository.findOne(predicate).orElse(null);
    }

     /**
     * 判断手机号码是否在云专家库下存在
     *
     * @param phoneNumber 手机号码
     * @return 执行反馈
     */
    public OrgUserPo findOrgUserByPhone(String phoneNumber) {
        QOrgUserPo qOrgUserPo = QOrgUserPo.orgUserPo;
        Predicate predicate = qOrgUserPo.id.isNotNull()
                .and(qOrgUserPo.deleted.isFalse())
                .and(qOrgUserPo.phoneNumber.eq(phoneNumber));
        return orgUserRepository.findOne(predicate).orElse(null);
    }

    /**
     * 判断手机号码是否在本机构下存在
     *
     * @param phoneNumber 手机号码
     * @param orgId       机构id
     * @return 执行反馈
     */
    public OrgUserRelPo phoneNumberExisted(String phoneNumber, Long orgId) {
        //---存在orgUser必存在orgUserRel对应关系----
        OrgUserPo orgUserPo = orgUserRepository.findByPhoneNumberAndDeletedIsFalse(phoneNumber);
        if(orgUserPo != null){
            QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
            Predicate predicate = qOrgUserRelPo.id.isNotNull().and(qOrgUserRelPo.user.id.eq(orgUserPo.getId())
                    .and(qOrgUserRelPo.org.id.eq(orgId)));
            return orgUserRelRepository.findOne(predicate).orElse(null);
        }
        return null;
    }
    /**
     * 判断姓名是否在本机构下存在
     *
     * @param name 姓名
     * @param orgId       机构id
     * @return 执行反馈
     */
    public OrgUserRelPo nameExisted(String name, Long orgId) {
        //---存在orgUser必存在orgUserRel对应关系----
        OrgUserPo orgUserPo = orgUserRepository.findByRealNameAndDeletedIsFalse(name);
        if(orgUserPo != null){
            QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
            Predicate predicate = qOrgUserRelPo.id.isNotNull().and(qOrgUserRelPo.user.id.eq(orgUserPo.getId())
                    .and(qOrgUserRelPo.org.id.eq(orgId)));
            return orgUserRelRepository.findOne(predicate).orElse(null);
        }
        return null;
    }

    /**
     * 1. excel 相同的手机号提示
     * 2. 姓名一样手机号一样，覆盖更新
     * 3. 手机号一样姓名不一样，提示
     *
     * @param file
     * @return
     */
    @Override
    public ApiResultDTO importExpertsByExcel(File file) {
        ApiResultDTO apiResultDTO;
        Workbook workbook = null;
        StringBuilder message = new StringBuilder();
        try {
            if (file.getPath().endsWith("xls")) {
                workbook = new HSSFWorkbook(new FileInputStream(file));
            } else if (file.getPath().endsWith("xlsx")) {
                workbook = new XSSFWorkbook(new FileInputStream(file));
            }
            // 获取第一个sheet
            Sheet sheet = workbook.getSheetAt(0);
            /**key的值为手机号，用来判断excel数据是否重复**/
            HashMap<String, String> map = new HashMap<>();
            List<OrgUserParamsDto> orgUserParamsDtoList = new ArrayList<>();
            // 获取每行中的字段,过滤首行说明和第二行字段信息
            for (int i = 2; i <= sheet.getLastRowNum(); i++) {
                Boolean flag = true;
                OrgUserParamsDto dto = new OrgUserParamsDto();
                dto.setOrgId(OrgAccountHelper.getOrgId());

                OrgExpertInfoParamsDto expertInfo = new OrgExpertInfoParamsDto();

                Row row = sheet.getRow(i);
                if (isRowEmpty(row)) {
                    continue;
                }

                // 获取姓名
                if (null == row.getCell(0)) {
                    message = message.append("第" + (i + 1) + "行的专家姓名不能为空;\n");
                    flag = false;
                } else {
                    dto.setRealName(RegularExpressionUtil.filterSpace(row.getCell(0).getStringCellValue()));
                }
                // 获取性别
//                if (null == row.getCell(1)) {
//                    message = message.append("第" + (i + 1) + "行的专家性别不能为空;\n");
//                    flag = false;
//                } else {
                    String sex = row.getCell(1).getStringCellValue().trim();
                    expertInfo.setGender(("男").equals(sex) ? "1" : "0");
//                }

                // 获取专家手机号
                if (null == row.getCell(2)) {
                    message = message.append("第" + (i + 1) + "行的专家手机号不能为空;\n");
                    flag = false;
                } else {
                    String phone = "";
                    if (CellType.NUMERIC.getCode() == row.getCell(2).getCellType()) {
                        DecimalFormat df = new DecimalFormat("#");
                        phone = df.format(row.getCell(2).getNumericCellValue());
                    } else {
                        phone = row.getCell(2).getStringCellValue().toString();
                    }
                    if(PhoneFormatCheckUtils.isChinaPhoneLegal(phone)){
                        if(map.containsKey(phone)){
                            message = message.append("第" + (i + 1) + "行的专家手机号在excel中已经存在，请修改;\n");
                            flag = false;
                        }else{
                            dto.setPhoneNumber(phone);
                        }
                    }else{
                        message = message.append("第" + (i + 1) + "行的专家手机号格式错误;\n");
                        flag = false;
                    }
                }
                // 获取专家工作单位
                if (null == row.getCell(3)) {
                    message = message.append("第" + (i + 1) + "行的专家工作单位不能为空;\n");
                    flag = false;
                } else {
                    dto.setUnit(row.getCell(3).getStringCellValue().trim());
                }

                // 获取研究领域
                if (null != row.getCell(4)) {
                    expertInfo.setResearchDomain(row.getCell(4).getStringCellValue().trim());
                }
                // 获取是否全职
                if (null == row.getCell(5)) {
                    message = message.append("第" + (i + 1) + "行的是否全职不能为空;\n");
                    flag = false;
                } else {
                    String fullStr = row.getCell(5).getStringCellValue().trim();
                    expertInfo.setFullTime(("是").equals(fullStr));
                }
                // 获取部门
                if (null == row.getCell(6)) {
                    message = message.append("第" + (i + 1) + "行的部门不能为空;\n");
                    flag = false;
                } else {
                    String company = row.getCell(6).getStringCellValue().trim();
                    expertInfo.setCompany(company);
                }
                // 获取职务
                if (null == row.getCell(7)) {
                    message = message.append("第" + (i + 1) + "行的职务不能为空;\n");
                    flag = false;
                } else {
                    String position = row.getCell(7).getStringCellValue().trim();
                    expertInfo.setPosition(position);
                }
                // 获取邮箱
                if (null == row.getCell(8)) {
                    message = message.append("第" + (i + 1) + "行的邮箱不能为空;\n");
                    flag = false;
                } else {
                    String email = row.getCell(8).getStringCellValue().trim();
                    dto.setMail(email);
                }
                dto.setExpertInfo(expertInfo);
                if (flag) {
                    //存入map  防止重复
                    map.put(dto.getPhoneNumber(), dto.getRealName());

                    orgUserParamsDtoList.add(dto);
                }

            }
            //循环入库
            if(!CollectionUtils.isEmpty(orgUserParamsDtoList)){
                for (OrgUserParamsDto dto : orgUserParamsDtoList) {
                    try {
                        //查询专家信息--手机号唯一  专家库是否已经存在
                        OrgUserPo orgUserPo = this.findOrgUserByPhone(dto.getPhoneNumber());
                        if(orgUserPo != null){
                            //当前机构是否已经存在
                            OrgUserRelPo orgUserRelPo = phoneNumberExisted(dto.getPhoneNumber(), dto.getOrgId());
                            if(orgUserRelPo == null){
                                //查询当前机构
//                                OrgPo orgPo = orgRepository.findById(dto.getOrgId()).orElse(null);
                                OrgDeptPo orgDeptPo = orgDeptRepository.findById(dto.getOrgId()).orElse(null);
                                //设置对应关系
                                orgUserRelPo = new OrgUserRelPo();
                                orgUserRelPo.setOrg(orgDeptPo);
                                orgUserRelPo.setUser(orgUserPo);
                                orgUserRelPo.setExpert(true);
                                orgUserRelPo.setMgr(false);
                                orgUserRelPo.setFullTime(dto.getExpertInfo().getFullTime());
                                orgUserRelPo.setLeader(dto.getExpertInfo().getLeader());
                                //保存对应关系
                                orgUserRelRepository.save(orgUserRelPo);
                                //保存专家信息--如果专家信息第一次录入
                                if(orgUserPo.getExpertInfo() == null){
                                    OrgExpertInfoPo orgExpertInfoPo = orgExpertInfoRepository.save(orgExpertInfoMapper.dto2po(dto.getExpertInfo()));
                                    orgUserPo.setExpertInfo(orgExpertInfoPo);
                                    orgUserRepository.save(orgUserPo);
                                }
                            }else{
                                //除了手机号 更新专家信息  PS: 2021年7月5日 提出需求
                                //更新是否全职
                                orgUserRelPo.setExpert(true);
                                orgUserRelPo.setFullTime(dto.getExpertInfo().getFullTime());

                                orgUserRelPo.setLeader(dto.getExpertInfo().getLeader());
                                orgUserRelRepository.save(orgUserRelPo);

                                //覆盖专家信息
                                OrgExpertInfoPo orgExpertInfoPo = orgUserPo.getExpertInfo();
                                //如果专家信息为空
                                if(orgUserPo.getExpertInfo() == null){
                                    OrgExpertInfoPo orgExpertInfoPoNew = orgExpertInfoRepository.save(orgExpertInfoMapper.dto2po(dto.getExpertInfo()));
                                    orgUserPo.setExpertInfo(orgExpertInfoPoNew);
                                    orgUserRepository.save(orgUserPo);
                                }else{
                                    orgExpertInfoPo.setGender(dto.getExpertInfo().getGender());
                                    orgExpertInfoPo.setCompany(dto.getExpertInfo().getCompany());
                                    orgExpertInfoPo.setResearchDomain(dto.getExpertInfo().getResearchDomain());
                                    orgExpertInfoRepository.save(orgExpertInfoPo);
                                }
                            }
                        }else{
                            //添加对应关系
                            this.create(dto, dto.getOrgId());
                        }
                    } catch (PhoneNumberExistedException e) {
                        continue;
                    }
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
            apiResultDTO = ApiResultGenerator.create("-1", "导入数据异常，请联系开发人员");
            return apiResultDTO;
        }
        if (message.length() == 0) {
            apiResultDTO = ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), "专家数据导入成功");
        } else {
            apiResultDTO = ApiResultGenerator.create("-1", message.toString());
        }

        return apiResultDTO;
    }


    private static boolean isRowEmpty(Row row) {
        if(row != null){
            for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
                Cell cell = row.getCell(i);
                if (cell != null && cell.getCellType() != CellType.BLANK.getCode()) {
                    return false;
                }
            }
        }
        return true;
    }

}
